#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
#include "./include/io_test.h"
#include "./include/protocol.h"
#include "./include/tcp_sxx.h"
int di_pins[IO_COUNT] = {0};  // 假设 GPIO 端口号
int do_pins[IO_COUNT] = {0};  // 假设 GPIO 端口号
#define EMIO_BASE   832

// 磁保持的四个引脚
int CBC_io_pins[4] = { EMIO_BASE+16, EMIO_BASE+17, EMIO_BASE+18, EMIO_BASE+19 }; 

int fast_io_pins[4] = { EMIO_BASE+20, EMIO_BASE+21, EMIO_BASE+22, EMIO_BASE+23 };  

// 检查文件是否存在
static int file_exists(const char *path) {
    struct stat st;
    return (stat(path, &st) == 0);
}

// 读取文件的辅助函数
int read_from_file(const char *path) 
{
    FILE *file = fopen(path, "r");
    int value;
    if (file == NULL) {
        perror("Error opening file");
        exit(1);
    }
    fscanf(file, "%d", &value);
    fclose(file);
    return value;
}
#include <stdio.h>
#include <stdlib.h>

// 设置GPIO状态的函数
void write_to_file(const char *path, int value) 
{
    FILE *file = fopen(path, "w");
    if (file == NULL) {
        perror("Error opening file for writing");
        exit(1);
    }
    
    // 将整数值写入文件
    if (fprintf(file, "%d", value) < 0) {
        perror("Error writing to file");
        fclose(file);  // 确保关闭文件句柄
        exit(1);
    }
    
    // 确保数据刷新到磁盘
    if (fflush(file) != 0) {
        perror("Error flushing file");
        fclose(file);
        exit(1);
    }
    
    fclose(file);
}
// 导出单个 GPIO
static int export_gpio(int gpio) {
    FILE *fp = fopen(SYS_GPIO_PATH "/export", "w");
    if (!fp) {
        #if !SILENT_MODE
        perror("无法打开export文件");
        #endif
        return -1;
    }
    
    fprintf(fp, "%d", gpio);
    fclose(fp);
    return 0;
}

// 配置GPIO方向为输入
static int set_gpio_direction(int gpio, int dir) {
    char path[128];
    snprintf(path, sizeof(path), SYS_GPIO_PATH "/gpio%d/direction", gpio);
    
    FILE *fp = fopen(path, "w");
    if (!fp) {
        #if !SILENT_MODE
        perror("无法打开export文件");
        #endif
        return -1;
    }
    if( dir )
    {
        fprintf(fp, "out");
    }
    else
    {
        fprintf(fp, "in");
    }
    fclose(fp);
    return 0;
}



void io_init( void )
{
    for (int i = 0; i < 32; i++) 
    {
        di_pins[i] = i + 992;
    }
    for (int i = 0; i < 32; i++) 
    {
        di_pins[i + 32] = i + 960;
    }
    for (int i = 0; i < 32; i++) 
    {
        // do_pins[i] = i + 896;
        do_pins[i] = i + 928;
    }
    for (int i = 0; i < 32; i++) 
    {
        // do_pins[i + 32] = i + 928;
        do_pins[i + 32] = i + 896;
    }

    for (int gpio = 960; gpio <= 1023; gpio++) 
    {
        char gpio_path[128];
        snprintf(gpio_path, sizeof(gpio_path), SYS_GPIO_PATH "/gpio%d", gpio);
        
        // 导出GPIO（忽略已导出的情况）
        if (!file_exists(gpio_path)) {
            if (export_gpio(gpio) != 0) {
                 #if !SILENT_MODE
                fprintf(stderr, "GPIO %d 导出失败\n", gpio);
                #endif
                continue;
            }
        }

        // 设置方向
        if (set_gpio_direction(gpio, 0) == 0) {
            #if !SILENT_MODE
            printf("GPIO %d 配置为输入模式\n", gpio);
            #endif
        } else {
            #if !SILENT_MODE
            fprintf(stderr, "GPIO %d 方向设置失败\n", gpio);
            #endif
        }
    }
    for (int gpio = 896; gpio <= 959; gpio++) 
    {
        char gpio_path[128];
        snprintf(gpio_path, sizeof(gpio_path), SYS_GPIO_PATH "/gpio%d", gpio);
        
        // 导出GPIO（忽略已导出的情况）
        if (!file_exists(gpio_path)) {
            if (export_gpio(gpio) != 0) {
                 #if !SILENT_MODE
                fprintf(stderr, "GPIO %d 导出失败\n", gpio);
                #endif
                continue;
            }
        }

        // 设置方向
        if (set_gpio_direction(gpio, 1) == 0) {
            #if !SILENT_MODE
            printf("GPIO %d 配置为输入模式\n", gpio);
            #endif
        } else {
            #if !SILENT_MODE
            fprintf(stderr, "GPIO %d 方向设置失败\n", gpio);
            #endif
        }
    }
    for (int gpio = EMIO_START; gpio <= EMIO_END; gpio++) {
        char gpio_path[128];
        snprintf(gpio_path, sizeof(gpio_path), SYS_GPIO_PATH "/gpio%d", gpio);
        
        // 导出GPIO（忽略已导出的情况）
        if (!file_exists(gpio_path)) {
            if (export_gpio(gpio) != 0) {
                 #if !SILENT_MODE
                fprintf(stderr, "GPIO %d 导出失败\n", gpio);
                #endif
                continue;
            }
        }

        if( gpio < EMIO_START + 16 )
        {
            // 设置方向
            if (set_gpio_direction(gpio, 1) == 0) {
                #if !SILENT_MODE
                printf("GPIO %d 配置为输模式\n", gpio);
                #endif
            } else {
                #if !SILENT_MODE
                fprintf(stderr, "GPIO %d 方向设置失败\n", gpio);
                #endif
            }
        }
        else
        {
            // 设置方向
            if (set_gpio_direction(gpio,0) == 0) {
                #if !SILENT_MODE
                printf("GPIO %d 配置为输入模式\n", gpio);
                #endif
            } else {
                #if !SILENT_MODE
                fprintf(stderr, "GPIO %d 方向设置失败\n", gpio);
                #endif
            }
        }
        
    }

}
void test_all_io( int cmd_fd )
{
    test_0_47_io_devices    ( cmd_fd );
    test_48_io_devices      ( cmd_fd );
    test_49_56_4CBC_devices ( cmd_fd );
    test_57_io_devices      ( cmd_fd );
    test_58_59_io_devices   ( cmd_fd );
    test_60_63_io_devices   ( cmd_fd );
} 

void test_0_47_io_devices(int cmd_fd) 
{
    char buf[0x10];
    //发送串口测试指令
    char _cmd[10];
    char path[64];
    int value_read = 0;
    for (int i = 0; i < 48; i++) 
    {
        for(int j = 0; j < 2; j++)
        {
            snprintf(_cmd, sizeof(_cmd), "<DO%d-%d>", i, j);
            send_command(cmd_fd, _cmd);
            usleep(50000);  //50ms

            memset( path, 0, strlen(path) );
            sprintf(path, "/sys/class/gpio/gpio%d/value", di_pins[i]);
            value_read = read_from_file(path); 
            sprintf(buf, "DO%d-value:%d", i, j);
            // 返回测试结果
            if(value_read == j)
            {
                send_response(cmd_fd, buf, "---OK");
                usleep(10000);  //10ms
                printf("✅ DO %d 测试通过!\n", i);
            }
            else
            {
                send_response(cmd_fd, buf, "---Fail");
                usleep(10000);  //10ms
                printf("❌ DO %d 测试失败!\n", i);
            }
            sleep(1);
        }
        printf( "\n");
    }
}
void test_48_io_devices( int cmd_fd )
{
    char cmd[100];
    char buf[0x10];
    //发送串口测试指令
    char _cmd[10];
    char path[64];
    int value_read = 0;
    int i = 48;
    for(int j = 0; j < 2; j++)
    {
        snprintf(_cmd, sizeof(_cmd), "<DO%d-%d>", i, j);
        send_command(cmd_fd, _cmd);
        usleep(50000);  //50ms

        memset( path, 0, strlen(path) );
        sprintf(path, "/sys/class/gpio/gpio%d/value", di_pins[i]);
        value_read = read_from_file(path); 
        sprintf(buf, "DO%d-value:%d", i, j);
        // 返回测试结果
        if(value_read == j)
        {
            send_response(cmd_fd, buf, "---OK");
            usleep(10000);  //10ms
            printf("✅ DO %d 测试通过!\n", i);
        }
        else
        {
            send_response(cmd_fd, buf, "---Fail");
            usleep(10000);  //10ms
            printf("❌ DO %d 测试失败!\n", i);
        }
        sleep(1);
    }
    printf( "\n");
}


void test_49_56_4CBC_devices( int cmd_fd )
{
    char cmd[100];
    char buf[0x10];
    //发送串口测试指令
    char _cmd[10];
    int value_read = 0;
    for (int channel = 0; channel < CIBAOCHI_COUNT; channel++) 
    {
        snprintf( _cmd, sizeof(_cmd), "<CBC-%d>", channel );
        send_command(cmd_fd, _cmd);

        usleep(600000);  //600ms
        
        sprintf(cmd, "/sys/class/gpio/gpio%d/value", CBC_io_pins[channel]);
        value_read = read_from_file(cmd); 
        sprintf(buf, "CBC-%d", channel);
        // 返回测试结果
        if( value_read == 0 )
        {
            send_response(cmd_fd, buf, "---OK");
            usleep(10000);  //10ms
            printf("✅ 磁保持 通道%d 触点吸合测试通过!\n", channel);
        }
        else
        {
            send_response(cmd_fd, buf, "---Fail");
            usleep(10000);  //10ms
            printf("❌ 磁保持 通道%d 触点吸合测试失败!\n", channel);
        }


        usleep(1200000);  //1200ms

        sprintf(cmd, "/sys/class/gpio/gpio%d/value", CBC_io_pins[channel]);
        int value_read = read_from_file(cmd); 
        sprintf(buf, "CBC-%d", channel);
        // 返回测试结果
        if( value_read == 1 )
        {
            send_response(cmd_fd, buf, "---OK");
            usleep(10000);  //10ms
            printf("✅ 磁保持 通道%d 触点吸合测试通过!\n", channel);
        }
        else
        {
            send_response(cmd_fd, buf, "---Fail");
            usleep(10000);  //10ms
            printf("❌ 磁保持 通道%d 触点吸合测试失败!\n", channel);
        }

        sleep(1);   //1s
        printf( "\n");
    }
}
void test_57_io_devices( int cmd_fd )
{
    char buf[0x10];
    //发送串口测试指令
    char _cmd[10];
    char path[64];
    int value_read = 0;
    int i = 57;
    for(int j = 0; j < 2; j++)
    {
        snprintf(_cmd, sizeof(_cmd), "<DO%d-%d>", i, j);
        send_command(cmd_fd, _cmd);
        usleep(50000);  //50ms

        memset( path, 0, strlen(path) );
        sprintf(path, "/sys/class/gpio/gpio%d/value", di_pins[i]);
        value_read = read_from_file(path); 
        sprintf(buf, "DO%d-value:%d", i, j);
        // 返回测试结果
        if(value_read == j)
        {
            send_response(cmd_fd, buf, "---OK");
            usleep(10000);  //10ms
            printf("✅ DO %d 测试通过!\n", i);
        }
        else
        {
            send_response(cmd_fd, buf, "---Fail");
            usleep(10000);  //10ms
            printf("❌ DO %d 测试失败!\n", i);
        }
        sleep(1);
    }
    printf( "\n");
}
void test_58_59_io_devices( int cmd_fd )
{
    char buf[0x10];
    //发送串口测试指令
    char _cmd[10];
    char path[64];
    int value_read = 0;
    for (int i = 58; i < 60; i++) 
    {
        for(int j = 0; j < 2; j++)
        {
            snprintf(_cmd, sizeof(_cmd), "<DO%d-%d>", i, j);
            send_command(cmd_fd, _cmd);
            usleep(50000);  //50ms

            memset( path, 0, strlen(path) );
            sprintf(path, "/sys/class/gpio/gpio%d/value", di_pins[i - 10]);
            value_read = read_from_file(path); 
            sprintf(buf, "DO%d-value:%d", i, j);
            // 返回测试结果
            if(value_read == j)
            {
                send_response(cmd_fd, buf, "---OK");
                usleep(10000);  //10ms
                printf("✅ DO %d 测试通过!\n", i);
            }
            else
            {
                send_response(cmd_fd, buf, "---Fail");
                usleep(10000);  //10ms
                printf("❌ DO %d 测试失败!\n", i);
            }
            sleep(1);
        }
        printf( "\n");
    }
}



void test_60_63_io_devices( int cmd_fd )
{

    char buf[0x10];
    //发送串口测试指令
    char _cmd[10];
    char path[64];
    int value_read = 0;
    for (int i = 60; i <= 63; i++) 
    {
        for(int j = 0; j < 2; j++)
        {
            snprintf(_cmd, sizeof(_cmd), "<DO%d-%d>", i, j);
            send_command(cmd_fd, _cmd);
            usleep(50000);  //50ms

            memset( path, 0, strlen(path) );
            sprintf(path, "/sys/class/gpio/gpio%d/value", fast_io_pins[i - 60]);
            value_read = read_from_file(path); 
            sprintf(buf, "DO%d-value:%d", i, j);
            // 返回测试结果
            if(value_read != j)
            {
                send_response(cmd_fd, buf, "---OK");
                usleep(10000);  //10ms
                printf("✅ DO %d 测试通过!\n", i);
            }
            else
            {
                send_response(cmd_fd, buf, "---Fail");
                usleep(10000);  //10ms
                printf("❌ DO %d 测试失败!\n", i);
            }
            sleep(1);
        }
        printf( "\n");
    }
    
}

void set_gpio_all_reset(int cmd_fd, __u_char* sendbuf)
{
    __u_char buffer[64] = {0};
    char path[64];

    for( int i=0; i<12; i++ )
    {
        memset( path, 0, strlen(path) );
        sprintf(path, "/sys/class/gpio/gpio%d/value", do_pins[i]);
        write_to_file( path, 0 );
        usleep(10000);  //10ms
    }

    packageinit_head( buffer );
    __u_short datapos = 6;

    buffer[datapos++] = Type_Gpio;
    datapos+=11;

    package_ending( sendbuf, buffer, &datapos );

    send(cmd_fd, buffer, datapos, 0);
}
void set_gpio_all_set(int cmd_fd, __u_char* sendbuf)
{
    __u_char buffer[64] = {0};
    char path[64];

    for( int i=0; i<12; i++ )
    {
        memset( path, 0, strlen(path) );
        sprintf(path, "/sys/class/gpio/gpio%d/value", do_pins[i]);
        write_to_file( path, 1 );
        usleep(50000);
    }

    packageinit_head( buffer );
    __u_short datapos = 6;

    buffer[datapos++] = Type_Gpio;
    // gpio:0-15
    buffer[datapos++] = 0xFF;
    buffer[datapos++] = 0xFF;

    // gpio:16-31
    buffer[datapos++] = 0xFF;
    buffer[datapos++] = 0xFF;

    // gpio:32-47
    buffer[datapos++] = 0xFF;
    buffer[datapos++] = 0xFF;

    // gpio:48
    buffer[datapos++] = 0x80;

    // gpio:49-56 (四路磁保持)
    buffer[datapos++] = 0x80 | 0x40 | 0x20 | 0x10;

    // gpio:57
    buffer[datapos++] = 0x00;

    // gpio:58-59
    buffer[datapos++] = 0x80 | 0x40;

    // gpio:49-56 (四路快速IO)
    buffer[datapos++] = 0x80 | 0x40 | 0x20 | 0x10;
    package_ending( sendbuf, buffer, &datapos );
    send(cmd_fd, sendbuf, datapos, 0);
}

void set_gpio_interval_1(int cmd_fd, __u_char* sendbuf)
{
    __u_char buffer[64] = {0};
    char path[64];
    int state;
    for( int i=0; i<12; i++ )
    {
        if( i % 2 == 0 )
        {
            state = 0;
        }
        else
        {
            state = 1;
        }
        memset( path, 0, strlen(path) );
        sprintf(path, "/sys/class/gpio/gpio%d/value", do_pins[i]);
        write_to_file( path, state );
        usleep(1000);
    }

    packageinit_head( buffer );
    __u_short datapos = 6;

    buffer[datapos++] = Type_Gpio;
    // gpio:0-15
    buffer[datapos++] = 0x55;
    buffer[datapos++] = 0x55;

    // gpio:16-31
    buffer[datapos++] = 0x55;
    buffer[datapos++] = 0x55;

    // gpio:32-47
    buffer[datapos++] = 0x55;
    buffer[datapos++] = 0x55;

    // gpio:48
    buffer[datapos++] = 0x80;

    // gpio:49-56 (四路磁保持)
    buffer[datapos++] = 0x00 | 0x40 | 0x00 | 0x10;

    // gpio:57
    buffer[datapos++] = 0x00;

    // gpio:58-59
    buffer[datapos++] = 0x00 | 0x40;

    // gpio:49-56 (四路快速IO)
    buffer[datapos++] = 0x00 | 0x40 | 0x00 | 0x10;
    package_ending( sendbuf, buffer, &datapos );
    send(cmd_fd, sendbuf, datapos, 0);
}

void set_gpio_interval_2(int cmd_fd, __u_char* sendbuf)
{
    __u_char buffer[64] = {0};
    char path[64];
    int state;
    for( int i=0; i<12; i++ )
    {
        if( i % 2 == 0 )
        {
            state = 1;
        }
        else
        {
            state = 0;
        }
        memset( path, 0, strlen(path) );

        sprintf(path, "/sys/class/gpio/gpio%d/value", do_pins[i]);
        write_to_file( path, state );
        usleep(1000);
    }

    packageinit_head( buffer );
    __u_short datapos = 6;

    buffer[datapos++] = Type_Gpio;
    // gpio:0-15
    buffer[datapos++] = 0xAA;
    buffer[datapos++] = 0xAA;

    // gpio:16-31
    buffer[datapos++] = 0xAA;
    buffer[datapos++] = 0xAA;

    // gpio:32-47
    buffer[datapos++] = 0xAA;
    buffer[datapos++] = 0xAA;

    // gpio:48
    buffer[datapos++] = 0x80;

    // gpio:49-56 (四路磁保持)
    buffer[datapos++] = 0x80 | 0x00 | 0x20 | 0x00;

    // gpio:57
    buffer[datapos++] = 0x00;

    // gpio:58-59
    buffer[datapos++] = 0x80 | 0x00;

    // gpio:49-56 (四路快速IO)
    buffer[datapos++] = 0x80 | 0x00 | 0x20 | 0x00;
    package_ending( sendbuf, buffer, &datapos );
    send(cmd_fd, sendbuf, datapos, 0);
}
void test_gpio(int cmd_fd, __u_char* sendbuf)
{
    set_gpio_all_reset( cmd_fd, sendbuf );
    set_gpio_all_set( cmd_fd, sendbuf );
}
void check_input_gpio_state( unsigned char* data, int choice )
{
    int ret = 0;
    char path[64];
    int value_read = 0;
    int state = 0;
    int channel = 0;
    
    if(choice == 1)
    {
        if( data[7] != 0xFF )
        {
            printf( "error! io 0-7 postback/getDis有错误, byte:0x%02X\n", data[7] );
            ret = -1;
        }
        if( data[8] != 0xFF )
        {
            printf( "error! io 8-15 postback/getDis有错误, byte:0x%02X\n", data[8] );
            ret = -2;
        }
        if( data[9] != 0xFF )
        {
            printf( "error! io 16-23 postback/getDis有错误, byte:0x%02X\n", data[9] );
            ret = -3;
        }
        if( data[10] != 0xFF )
        {
            printf( "error! io 24-31 postback/getDis有错误, byte:0x%02X\n", data[10] );
            ret = -4;
        }
        if( data[11] != 0xFF )
        {
            printf( "error! io 32-39 postback/getDis有错误, byte:0x%02X\n", data[11] );
            ret = -5;
        }
        if( data[12] != 0xFF )
        {
            printf( "error! io 40-47 postback/getDis有错误, byte:0x%02X\n", data[12] );
            ret = -6;
        }
        if( data[13] != 0xF0 )
        {
            printf( "error! io 50 52 54 56 有错误, 关于4路磁保持, byte:0x%02X\n", data[13] );
            ret = -7;
        }
        if( data[14] != 0xFF)
        {
            printf( "error! io 48 49 51 53 55 57 58 59 有错误, 关于外部输入离散量, byte:0x%02X\n", data[14] );
            ret = -8;
        }
        if( data[15] != 0xF0)
        {
            printf( "error! io 60 61 62 63 有错误, 关于外部输入离散量, byte:0x%02X\n", data[15] );
            ret = -9;
        }

        
    }
    else if( choice == 2 )
    {
        if( data[7] != 0x00 )
        {
            printf( "error! io 0-7 postback/getDis有错误, byte:0x%02X\n", data[7] );
            ret = -1;
        }
        if( data[8] != 0x00 )
        {
            printf( "error! io 8-15 postback/getDis有错误, byte:0x%02X\n", data[8] );
            ret = -2;
        }
        if( data[9] != 0x00 )
        {
            printf( "error! io 16-23 postback/getDis有错误, byte:0x%02X\n", data[9] );
            ret = -3;
        }
        if( data[10] != 0x00 )
        {
            printf( "error! io 24-31 postback/getDis有错误, byte:0x%02X\n", data[10] );
            ret = -4;
        }
        if( data[11] != 0x00 )
        {
            printf( "error! io 32-39 postback/getDis有错误, byte:0x%02X\n", data[11] );
            ret = -5;
        }
        if( data[12] != 0x00 )
        {
            printf( "error! io 40-47 postback/getDis有错误, byte:0x%02X\n", data[12] );
            ret = -6;
        }
        if( data[13] != 0x00 )
        {
            printf( "error! io 50 52 54 56 有错误, 关于4路磁保持, byte:0x%02X\n", data[13] );
            ret = -7;
        }
        if( data[14] != 0x00 )
        {
            printf( "error! io 48 49 51 53 55 57 58 59 有错误, 关于外部输入离散量, byte:0x%02X\n", data[14] );
            ret = -8;
        }
        if( data[15] != 0x00 )
        {
            printf( "error! io 60 61 62 63 有错误, 关于外部输入离散量, byte:0x%02X\n", data[15] );
            ret = -9;
        }
    }
    else if( choice == 3 )
    {
        if( data[7] != 0x55 )
        {
            printf( "error! io 0-7 postback/getDis有错误, byte:0x%02X\n", data[7] );
            ret = -1;
        }
        if( data[8] != 0x55 )
        {
            printf( "error! io 8-15 postback/getDis有错误, byte:0x%02X\n", data[8] );
            ret = -2;
        }
        if( data[9] != 0x55 )
        {
            printf( "error! io 16-23 postback/getDis有错误, byte:0x%02X\n", data[9] );
            ret = -3;
        }
        if( data[10] != 0x55 )
        {
            printf( "error! io 24-31 postback/getDis有错误, byte:0x%02X\n", data[10] );
            ret = -4;
        }
        if( data[11] != 0x55 )
        {
            printf( "error! io 32-39 postback/getDis有错误, byte:0x%02X\n", data[11] );
            ret = -5;
        }
        if( data[12] != 0x55 )
        {
            printf( "error! io 40-47 postback/getDis有错误, byte:0x%02X\n", data[12] );
            ret = -6;
        }
        if( data[13] != 0x50 )
        {
            printf( "error! io 50 52 54 56 有错误, 关于4路磁保持, byte:0x%02X\n", data[13] );
            ret = -7;
        }
        if( data[14] != 0x55 )
        {
            printf( "error! io 48 49 51 53 55 57 58 59 有错误, 关于外部输入离散量, byte:0x%02X\n", data[14] );
            ret = -8;
        }
        if( data[15] != 0x50 )
        {
            printf( "error! io 60 61 62 63 有错误, 关于外部输入离散量, byte:0x%02X\n", data[15] );
            ret = -9;
        }
    }
    else if( choice == 4 )
    {
        if( data[7] != 0xAA )
        {
            printf( "error! io 0-7 postback/getDis有错误, byte:0x%02X\n", data[7] );
            ret = -1;
        }
        if( data[8] != 0xAA )
        {
            printf( "error! io 8-15 postback/getDis有错误, byte:0x%02X\n", data[8] );
            ret = -2;
        }
        if( data[9] != 0xAA )
        {
            printf( "error! io 16-23 postback/getDis有错误, byte:0x%02X\n", data[9] );
            ret = -3;
        }
        if( data[10] != 0xAA )
        {
            printf( "error! io 24-31 postback/getDis有错误, byte:0x%02X\n", data[10] );
            ret = -4;
        }
        if( data[11] != 0xAA )
        {
            printf( "error! io 32-39 postback/getDis有错误, byte:0x%02X\n", data[11] );
            ret = -5;
        }
        if( data[12] != 0xAA )
        {
            printf( "error! io 40-47 postback/getDis有错误, byte:0x%02X\n", data[12] );
            ret = -6;
        }
        if( data[13] != 0xA0 )
        {
            printf( "error! io 50 52 54 56 有错误, 关于4路磁保持, byte:0x%02X\n", data[13] );
            ret = -7;
        }
        if( data[14] != 0xAA )
        {
            printf( "error! io 48 49 51 53 55 57 58 59 有错误, 关于外部输入离散量, byte:0x%02X\n", data[14] );
            ret = -8;
        }
        if( data[15] != 0xA0 )
        {
            printf( "error! io 60 61 62 63 有错误, 关于外部输入离散量, byte:0x%02X\n", data[15] );
            ret = -9;
        }
    }
    int set_state;

    // 测试工装检测状态 0-47 58-59
    for(int i = 0; i < 50; i++) 
    {
        if(i > 47)
        {
            channel = i + 10;
        }
        else
        {
            channel = i;
        }
        
        if(choice == 1)
		{
			set_state = 0;
		}
		else if( choice == 2 )
		{
			set_state = 1;
		}
		else if( choice == 3 )
		{
			if( i % 2 == 0)	
			{
				set_state = 1;
			}
			else
			{
				set_state = 0;
			}
		}
		else if( choice == 4 )
		{
			if( i % 2 == 0)	
			{
				set_state = 0;
			}
			else
			{
				set_state = 1;
			}
		}
        memset( path, 0, strlen(path) );
        sprintf(path, "/sys/class/gpio/gpio%d/value", di_pins[i]);
        value_read = read_from_file(path); 
        if(value_read != set_state)
        {
            printf("error! 测试工装检测 输出离散量 状态错误! 期望:DO%d-value:%d  实际:DO%d-value:%d(0-低  1-高)\n",channel, set_state, channel,value_read );
            ret = -10;
        }
    }
    // 测试工装检测状态 49-56
    for(int i = 0; i < CIBAOCHI_COUNT; i++) 
    {
        if(choice == 1)
		{
			set_state = 0;
		}
		else if( choice == 2 )
		{
			set_state = 1;
		}
		else if( choice == 3 )
		{
			if( i % 2 == 0)	
			{
				set_state = 1;
			}
			else
			{
				set_state = 0;
			}
		}
		else if( choice == 4 )
		{
			if( i % 2 == 0)	
			{
				set_state = 0;
			}
			else
			{
				set_state = 1;
			}
		}
        memset( path, 0, strlen(path) );
        sprintf(path, "/sys/class/gpio/gpio%d/value", CBC_io_pins[i]);
        value_read = read_from_file(path); 
        if(value_read != set_state)
        {
            if( state )
            {
                printf("error! 测试工装检测 磁保持吸合 状态错误! CBC-%d\n" , i );
            }
            else 
            {
                printf("error! 测试工装检测 磁保持断开 状态错误! CBC-%d\n" , i );
            }
            ret = -11;
        }
    }
    // 测试工装检测状态 60-63
    for(int i = 0; i < 4; i++) 
    {
        if(choice == 1)
		{
			set_state = 0;
		}
		else if( choice == 2 )
		{
			set_state = 1;
		}
		else if( choice == 3 )
		{
			if( i % 2 == 0)	
			{
				set_state = 1;
			}
			else
			{
				set_state = 0;
			}
		}
		else if( choice == 4 )
		{
			if( i % 2 == 0)	
			{
				set_state = 0;
			}
			else
			{
				set_state = 1;
			}
		}
        channel = 60 + i;
        memset( path, 0, strlen(path) );
        sprintf(path, "/sys/class/gpio/gpio%d/value", fast_io_pins[i]);
        value_read = read_from_file(path); 
        if(value_read == set_state)
        {
            printf("error! 测试工装检测 快速IO 状态错误! DO-%d\n", channel );
            ret = -11;
        }
    }
    if( ret == 0 )
    {
        printf("✅ 离散量指令%d 测试通过!\n", choice );
    }
    else
    {
        printf("❌ 离散量指令%d 测试失败!\n", choice );
    }
    printf("\n");
    
}


void handle_choice_io(int choice, int cmd_fd, char* sendbuf )
{
    int valread;
    int count = 0;
    unsigned short len = 0;
    unsigned char buffer[BUFFER_SIZE];
    unsigned char get_buf[BUFFER_SIZE];
    
    switch (choice) 
    {
        case 1:
            set_gpio_all_set( cmd_fd, sendbuf );
            break;

        case 2:
            set_gpio_all_reset( cmd_fd, sendbuf );
            break;

        case 3:
            set_gpio_interval_1( cmd_fd, sendbuf );
            break;

        case 4:
            set_gpio_interval_2( cmd_fd, sendbuf );
            break;

        case 5:
            return ;
       
        default:
            printf("无效选项，请重新输入\n");
            return ;
    }
    recv_tcp_data_discard( cmd_fd,10 );

    while(1)
    {
        usleep(100000);  //1s
        valread = recv(cmd_fd, buffer, BUFFER_SIZE, 0);

        if(valread > 0)
        {
            if( buffer[6] == Type_Gpio )
            {
                if( count++ > 50 )
                {
                    printf("未接收到正确数据!\n");
                    return ;
                }
                break;
            }
        }
        if( count++ > 50 )
        {
            printf("未接收到正确数据!\n");
            return ;
        }
    }        
    len = buffer[5] << 8 | buffer[4];
    printf("[输入离散量周期数据] 接收数据长度:%d 数据:", len);
    for (int i = 0; i < len; i++) 
    {
        // 以大写十六进制格式输出，宽度为2，不足补0
        printf("0x%02X ", buffer[i]); 
    }
    printf("\n");
    handle_tcp_recv_package(len,buffer,choice);
    
    return ;

}